import AST.ASTCommand;
import AST.ASTIExpression;
import AST.ASTProgram;
import AST.ASTRepetition;
import AST.ASTSequence;
import AST.ASTIExpression;
import AST.ASTVariable;


public class Parser {
	public Parser(Lexer lex)
	{
		_lex = lex;
		_lexeme = _lex.Next();
	}
	
	public ASTProgram ParseProgram()
	{	
		System.out.println("Parsing program");
		ASTProgram program = new ASTProgram();
		ASTIExpression expression = ParseExpression();
		program.setExpression(expression);
		return program;
	}
	
	private ASTRepetition ParseRepetition()
	{
		System.out.println("Repetition " + _lexeme._token);
		
		ASTRepetition repetition = new ASTRepetition();
		
		_lexeme = _lex.Next();
		if (_lexeme._token != Token.Token_LPAREN)
		{
			Panic("LParen in while expression lost." + _lexeme._token);
			return null;
		}
		
		ASTVariable var = ParseVariable();
		
		if (var != null)
		{
			repetition.setVariable(var);
		}
		else
		{
			Panic("Variable in while expression lost.");
			return null;
		}
		
		_lexeme = _lex.Next();
		if (_lexeme._token != Token.Token_RPAREN)
		{
			Panic("RParen in while expression lost.");
			return null;
		}
		_lexeme = _lex.Next();
		ASTIExpression expression = ParseExpression();
		if (expression != null)
		{
			repetition.setExpression(expression);
		}
		else
		{
			Panic("Expression in while expression lost.");
			return null;
		}
		
		return repetition;
	}
	
	private ASTVariable ParseVariable() {
		System.out.println("Variable");
		Lexeme _lexeme = _lex.Next();
		ASTVariable var = new ASTVariable();
		if (_lexeme._token == Token.Token_IDENT)
		{
			var.setValue(_lexeme._value);
			return var;
		}
		else
		{
			Panic("Variable identifier lost.");
			return null;
		}		
	}

	private ASTSequence ParseSequence()
	{
		System.out.println("Sequence");
		ASTSequence sequence = new ASTSequence();
		//_lexeme = _lex.Next();
		
		while (_lexeme._token == Token.Token_COMMAND)
		{
			System.out.println("Command");
			ASTCommand command = new ASTCommand();
			command.setValue(_lexeme._value);
			sequence.addCommand(command);
			_lexeme = _lex.Next();
			if (_lexeme._token != Token.Token_SEMICOLON)
			{
				Panic("Semicolon  after command lost.");
				return null;
			}
			
			_lexeme = _lex.Next();
		}
		if (_lexeme._token != Token.Token_KEYWORD && _lexeme._token != Token.Token_EOF)
		{
			Panic("Sequence end error:unexpected "+ _lexeme._token);
			System.out.println();
		}
		
		return sequence;
	}
	
	private ASTIExpression ParseExpression()
	{
		System.out.println("Expression");
		ASTIExpression expression;
		
			if (_lexeme._token == Token.Token_KEYWORD)//Keyword is just while now
			{
				expression = ParseRepetition();
				return expression;
			}
			else if (_lexeme._token == Token.Token_COMMAND)
			{
				expression = ParseSequence();
				return expression;
			}
			else
			{
				Panic("Unexpected token:" + _lexeme._token);
				return null;
			}
		
	}
	
	private void Panic(String errorMessage)
	{
		System.out.println(errorMessage + " Panic!");
		/*while (_lexeme._token != Token.Token_SEMICOLON)
		{
			_lexeme = _lex.Next();
		}
		_lexeme = _lex.Next();*/			
	}
	
	private Lexeme _lexeme;
	private Lexer _lex;
}
